package com.cherrypt.api.core.controller;

import com.cherrypt.api.common.enums.FileTypeEnum;
import com.cherrypt.api.common.enums.ResultEnum;
import com.cherrypt.api.common.enums.UserInfoEnum;
import com.cherrypt.api.common.exception.TipException;
import com.cherrypt.api.common.util.DateUtils;
import com.cherrypt.api.common.util.ImageUtils;
import com.cherrypt.api.common.constant.WebConst;
import com.cherrypt.api.common.util.PathUtils;
import com.cherrypt.api.core.util.JwtUtils;
import com.cherrypt.api.model.bo.AttachBo;
import com.cherrypt.api.model.dataobject.UserInfo;
import com.cherrypt.api.model.dto.SignRecordDto;
import com.cherrypt.api.model.dto.UserDto;
import com.cherrypt.api.core.service.AttachService;
import com.cherrypt.api.core.service.SignRecordService;
import com.cherrypt.api.core.service.UserInfoService;
import com.cherrypt.api.core.service.UserService;
import com.cherrypt.api.core.service.impl.AvatarStorageService;
import com.cherrypt.api.core.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;

@Api(tags = "用户获取信息、签到、上传头像")
@RestController
@RequestMapping(value = "${api.url.user.value}")
public class UserController {
    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Value("${api.file.staticAccessPath}")
    private String staticAccessPath;

    @Value("${api.file.avatarFolder}")
    private String avatarFolder;

    @Autowired
    private UserService userService;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private SignRecordService signRecordService;

    @Autowired
    private AttachService attachService;

    @Autowired
    private AvatarStorageService avatarStorageService;

    @ApiOperation(value = "根据用户token获取用户信息")
    @ApiImplicitParam(name = "token", value = "Header携带token辨识用户", example = WebConst.TOKEN,
            dataType = "string", paramType = "header", required = true)
    @GetMapping(value = "")
    public ResponseEntity<UserDto> get(@ApiIgnore HttpServletRequest request) throws TipException {
        Integer userId = JwtUtils.getUserIdFromRequest(request);
        UserDto userDTO = userService.getUserById(userId);
        if (userDTO.getStatus() == UserInfoEnum.BAN.getCode()) {
            throw new TipException(ResultEnum.ACCOUNT_BAN_ERROR);
        }
        userDTO.setIsSigned(signRecordService.isSigned(userId));
        return ResponseEntity.ok(userDTO);
    }

    @ApiOperation(value = "根据用户名判断用户是否存在")
    @GetMapping(value = "${api.url.user.getUserByUsername}")
    public ResponseEntity<Boolean> getUserByUsername(@PathVariable("username") String username) throws TipException {
        UserInfo userInfo = userInfoService.getUserByUsername(username);
        return ResponseEntity.ok(userInfo != null);
    }

    @ApiOperation(value = "根据用户uid获取用户信息")
    @ApiImplicitParam(name = "token", value = "Header携带token辨识用户", example = WebConst.TOKEN,
            dataType = "string", paramType = "header", required = true)
    @GetMapping(value = "${api.url.user.getUserByUid}")
    public ResponseEntity<UserDto> getUserByUid(@PathVariable("uid") String uid, @ApiIgnore HttpServletRequest request) {
        int userId = Integer.valueOf(uid);
        UserDto userDTO = userService.getFriendById(userId);
        return ResponseEntity.ok(userDTO);
    }

    @ApiOperation(value = "根据用户token签到")
    @ApiImplicitParam(name = "token", value = "Header携带token辨识用户", example = WebConst.TOKEN,
            dataType = "string", paramType = "header", required = true)
    @PostMapping(value = "${api.url.user.signed}")
    public ResponseEntity<SignRecordDto> signed(@ApiIgnore HttpServletRequest request) throws TipException {
        Integer userId = JwtUtils.getUserIdFromRequest(request);
        SignRecordDto signRecordDto = signRecordService.signed(userId);
        return ResponseEntity.ok(signRecordDto);
    }

    @ApiOperation(value = "用户上传头像")
    @ApiImplicitParam(name = "token", value = "Header携带token辨识用户", example = WebConst.TOKEN,
            dataType = "string", paramType = "header", required = true)
    @PostMapping(value = "${api.url.user.avatar}", produces = WebConst.JSON)
    public ResponseEntity<String> avatarUpload(MultipartFile image, @ApiIgnore HttpServletRequest request)
            throws TipException, IOException {
        // 检查是不是图片
        if (image == null || !ImageUtils.isImage(image.getInputStream()) || image.getContentType() == null) {
            throw new TipException(ResultEnum.IMAGE_TYPE_ERROR);
        }
        // 文件名与数据库一一对应
        // 根据当前时间戳的hash生成文件名
        String fileName = DigestUtils.md5Hex(String.valueOf(System.currentTimeMillis()));
        String fileType = image.getContentType().replace("image/", "");
        String relativePath = avatarStorageService.getRootLocation().toString() + PathUtils.SPEA
                + DateUtils.getDatePath()
                + fileName + "." + fileType;
        Integer userId = JwtUtils.getUserIdFromRequest(request);
        // 存储到本地
        if (ImageUtils.saveImage(image.getInputStream(), fileType, new File(relativePath))) {
            // 插入数据库
            // 存储相对位置
            attachService.save(AttachBo.getAttach(
                    userId, image.getOriginalFilename(), image.getSize(), relativePath, FileTypeEnum.IMAGE.getName()));
            String url = CherryUtils.getServerUrl(request) + PathUtils.SPEA_URL +
                    staticAccessPath + PathUtils.SPEA_URL +
                    relativePath.replaceFirst(avatarStorageService.getRootLocation().toString(), avatarFolder);
            // 更新用户信息
            UserInfo userInfo = new UserInfo();
            userInfo.setUid(userId);
            userInfo.setAvatarUrl(url);
            userInfoService.updateUserInfoByUid(userInfo);
            logger.info("uid: {}, 上传了新头像: {}", userId, url);
            return ResponseEntity.ok(JackJsonUtils.json("url", url));
        } else {
            throw new TipException(ResultEnum.UPLOAD_IMAGE_ERROR);
        }
    }
}
